package lexico;

import java.util.ArrayList;
import java.util.List;
import javax.swing.JOptionPane;
import token.TokenType;
import token.Token;
import token.TokenAll;

public class Automato {

    List<Token> listagem = new ArrayList<Token>();
    List<Erro> listErro = new ArrayList<Erro>();
    char[] fonte;
    int STATE;
    int ponteiro;
    private int linha = 0;
    int coment = 0;

    String quebras = " ;\t+-*/=!><&|\"_(){}[]'";

    /**
     * Metodo que recebe uma linha de código e separa os Tokens da linguagem adicionando estes a uma lista
     * @param textoFonte
     */
    public void controle(String textoFonte){ //A cada linha um nova linha, um novo textoFonte

        //incrementa o contador de linhas
        linha++;

        ponteiro = 0;
        STATE = 0;

        //Cria um vetor de caracteres com a linha
        this.fonte = (textoFonte).toCharArray();
        //Inicia a maquina de estados para a linha
        System.out.println("Linha --------------------------------"+linha );
        do {
            switch (STATE) {
                //1o estado, é um estado de decisão onde será escolhido qual tipo de Token será trabalhado
                case 0: {
                    primeiroEstado();
                    System.out.print("Primeiro estado: ");
                    System.out.println("Valor do ponteiro-->"+ponteiro);
                    break;
                }
                //2o estado...
                case 1: {
                    identificador();
                    break;
                }
                case 2: {
                    numero();
                    break;
                }
                case 3: {
                    operador();
                    break;
                }
                case 4: {
                    comentario();
                    break;
                }
                case 5: {
                    delimitador();
                    System.out.print("Delimitador: ");
                    System.out.println("Valor do ponteiro-->"+ponteiro);
                    break;
                }
                case 6: {
                    caractere();
                    break;
                }
                case 7:
                    string();
                    break;
                case 8: {
                    System.out.print("Caracter invalido: ");
                    System.out.println("Valor do ponteiro-->"+ponteiro);
                    caracterInvalido();
                    break;
                }
            }
        } while (this.incrPonteiro()); //Se possível, incrementa o ponteiro e continua o laço
        
    }


    public void imprimeLista()
    {
        //IMPRIMINDO A LISTAGEM
        System.out.println("\n::Lista de Tokens \n");
        for (Token obj : listagem) {
            TokenAll tipo = obj.getTipo();
            if (tipo.toString().equals("NUMERO")) {
                System.out.println("tipo: " + obj.getTipo() + "\n    valor: " + obj.getValorNum() + "\n    linha: " + obj.getLinha());
            } else {
                System.out.println("tipo: " + obj.getTipo() + "\n    valor: " + obj.getValor() + "\n    linha: " + obj.getLinha());
            }
        }
        System.out.println("\n=================\n::Lista de Erros\n");
        for (Erro obj : this.listErro) {
            System.out.println("tipo " + obj.getTipo() + ", valor " + obj.getValor() + ", linha " + obj.getLinha());
        }
    }

    /*
     * Verifica se o ponteiro está alocado na última posição da string. Retorna 'true' caso esteja,
     *retorna 'false' se contrário.
     */

    private boolean isFimPonteiro() {
        if (ponteiro == fonte.length - 1) {
            return true;
        } else {
            return false;
        }
    }

    /*
     * Verifica a possibilidade de incremento do ponteiro antes de assim o efetuar. Retorna 'true'
     * caso seja possível o incrementando e 'false' para o contrário.
     */
    private boolean incrPonteiro() //Caso não tenha chegado ao fim, incrementa e retorna "true"
    {
        if (ponteiro < fonte.length - 1) {
            ponteiro++;
            return true;
        } else {
            return false;
        }
    }

    /*
     * Corresponde ao primeiro estado do autômato. Se caracteriza pela especificação do token
     * a partir da identificação do primeiro caratere.
     */
    private void primeiroEstado() {

        if(ponteiro == fonte.length)
        {
            //Caso já tenha chegado ao final da linha não faz nada
        }else if ((fonte[ponteiro] == ' ' || fonte[ponteiro] == '\t') && coment == 0) {
            //Caso tenha encontrado espaço ou tabulação continua no estado de procura (Zero)
            STATE = 0;
        } else if(coment == 1)
        {
            //Caso esteja dentro de um comentário de bloco vai para o estado de comentário (4)
            STATE = 4;
        }else {
            if (Character.isLetter(fonte[ponteiro]) || fonte[ponteiro]=='_') {
                //caso seja uma letra vai para o estado de identifacador (Um)
                System.out.println("::Identificador");
                STATE = 1;
                ponteiro--;
            } else
                if (fonte[ponteiro] == '-') //caso seja um numero ou '-'
                {
                    STATE = 3;      //Operador SUBNTRAÇÃO
                    ponteiro--;
                }else
                    if (Character.isDigit(fonte[ponteiro])) { //caso seja um numero ou '-'
                        //System.out.println("::Numero");
                        STATE = 2;
                        ponteiro--;
                        //System.out.println(ponteiro);
                    } else if (ehOperador()) {
                        //System.out.println("::Operador");
                        STATE = 3;
                        ponteiro--;
                    }else if (fonte[ponteiro] == '\'') {
                        //System.out.println("::CHAR");
                        //Vai para o estado de caractere
                        STATE = 6;
                        ponteiro--;
                    } else if (fonte[ponteiro] == '/' || fonte[ponteiro] == 47) //Testa as possibilidades para o character "/"
                    {
                        try
                        {
                            if (fonte[ponteiro + 1] == '*' || fonte[ponteiro + 1] == 42) {
                                //System.out.println("::Comentário Parágrafo");
                                ponteiro++;
                                if(ponteiro == fonte.length-1)   // Verifica se a linha contém apenas o /*
                                {
                                    coment = 1;
                                    STATE = 0;
                                }else
                                STATE = 4;
                            } else if (fonte[ponteiro + 1] == '/' || fonte[ponteiro + 1] == 47) {
                                //System.out.println("::Comentário Linha: PULAR A LINHA");
                                pularLinha();
                                STATE = 0;
                                ponteiro = fonte.length - 1;  //Encerra a linha
                            } else if (Character.isDigit(fonte[ponteiro + 1]) || Character.isLetter(fonte[ponteiro + 1]) || Character.isSpaceChar(fonte[ponteiro + 1])) {
                                //System.out.println("::Operador");
                                STATE = 3;
                                ponteiro--;
                            }
                        }
                        //Caso tenha chegado ao final da linha a barra é um operador
                        catch (ArrayIndexOutOfBoundsException e) {
                            //System.out.println("::Operador");
                            STATE = 3;
                            ponteiro--;
                        }
                    } else if (isDelimitador()) {
                        //System.out.println("::Delimitador");
                        STATE = 5;
                        ponteiro--;
                    } else if (fonte[ponteiro] == '"' || fonte[ponteiro] == 34) {
                        STATE = 7;
                        ponteiro--;
                    } else {
                this.STATE = 8;
                ponteiro--;
            }
        }
    }

    /**
     * Identica um separador
     * @param c
     * @return
     */
    private boolean isQuebra (char c) {

        for(int i = 0; i < quebras.length(); i++){
            if(c == quebras.charAt(i))
                return true;
        }
        return false;
    }


    /*
     *
     */
    private void identificador() {
        String aux = "";
        //se for letra ou numero ou '_'...
        int start = ponteiro;               //Pega a posição inicial do ponteiro, para posteriormente verficar se o caractere inicial é uma letra
        while (Character.isLetter(fonte[ponteiro]) || Character.isDigit(fonte[ponteiro]) || fonte[ponteiro] == '_') {
            aux = aux + fonte[ponteiro];
            if (!incrPonteiro()) {
                break;
            }
        }
        
        //TODO Consumir caracteres inválidos aqui
        if(this.isValidChar(fonte[ponteiro]) && Character.isLetter(fonte[start]))
        {
            if(aux.length()<=32)        //Limita o tamanho do identificador em 32 caracteres
            {
                listagem.add(new Token(TokenAll.IDENTIFICADOR, aux, linha, TokenType.IDENTIFICADOR));
                STATE = 0;

                //Verifica Palavra-Chave
                TokenAll[] tipos;
                tipos = TokenAll.values();
                for(int x = 0; x < 21; x++)
                {
                    if(listagem.get(listagem.size() - 1).getValor().equals(tipos[x].toString()))
                    {
                         listagem.get(listagem.size() - 1).seteToke(TokenType.PALAVRACHAVE);
                         listagem.get(listagem.size() - 1).setTipo(TokenAll.valueOf(aux));
                         break;
                    }
                }
                if(!isFimPonteiro() || !(Character.isLetter(fonte[ponteiro])|| Character.isDigit(fonte[ponteiro]) || fonte[ponteiro]=='_'))
                    ponteiro--;
            }
            else
                this.listErro.add(new Erro("IDENTIFICADOR MUITO GRANDE", aux, linha));
        }
        else
        {
            while(!this.isQuebra(fonte[ponteiro])|| !this.isValidChar(fonte[ponteiro]))
            {
                aux = aux + fonte[ponteiro];
                if(!this.incrPonteiro())
                    break;
            }
            this.listErro.add(new Erro("IDENTIFICADOR INVALIDO", aux, linha));
        }

    }

    private void numero() {
        String aux = "";
        int flag = 0;
        boolean isFloat = false;
        boolean isInvalid = false;
        float aux1;
        if(!this.isValidChar(fonte[ponteiro]))
        {
            isInvalid = true;
            aux = aux + fonte[ponteiro];
            this.incrPonteiro();
        }
        while (Character.isDigit(fonte[ponteiro])) {
            aux = aux + fonte[ponteiro];
            if (!incrPonteiro()) //Se não for mais possível incrementar o ponteiro...
                break;
        }
        System.out.println("Valor no aux: "+aux);
        if (fonte[ponteiro] == '.') {
            isFloat = true;
            aux = aux + '.';
            while (incrPonteiro() && Character.isDigit(fonte[ponteiro])) {
                aux = aux + fonte[ponteiro];
            }
        }
        if(Character.isLetter(fonte[ponteiro]) || !this.isValidChar(fonte[ponteiro]) || (fonte[ponteiro])=='_' || isInvalid)
        {
            System.out.println("Entra aqui?");
            flag = 1;
            listErro.add(new Erro("NUMERO INVALIDO", aux, linha));
            STATE = 0;
            return;
        }
        aux1 = Float.parseFloat(aux);
        //Esse trecho veriifca se o número extrapola o tamanho permitido pelo java
        if(isFloat)                 //Verifica se é float
        {
            if(Float.isInfinite(aux1))  //Verifica se deu estouro (Infinity)
            {
                listErro.add(new Erro("REAL MUITO GRANDE", aux, linha));
                ponteiro++;
                STATE = 0;
                return;
            }
        }
        else            //Caso não seja float, passa para as verificações pertinentes ao inteiro
        {
            try
            {
                int aux2 = Integer.parseInt(aux);
            }
            catch(NumberFormatException e)
            {
                listErro.add(new Erro("INTEIRO MUITO GRANDE", aux, linha));
                ponteiro++;
                STATE = 0;
                return;
            }
        }

        
        if(isFimPonteiro() && Character.isDigit(fonte[ponteiro]))
            ponteiro++;

        ponteiro--;
        STATE = 0;

        if(flag == 0)
            listagem.add(new Token(TokenAll.NUMERO, aux1, linha, TokenType.NUMERO));

        flag = 0;
        //System.out.println(listagem.get(listagem.size()-1).getValorNum());
    }

    /*
     * Este metodo analisa cada caracter por caracter,
     * reconhecendo e classificando os operadores da linguagem,
     * alem de identificar os possiveis erros encontrados.
     */
    public void operador() {
        switch (fonte[ponteiro]) {
            case 33:
                    try {
                        if (fonte[ponteiro + 1] == 61) {                            // Se o próximo caractere for "="
                            listagem.add(new Token(TokenAll.DIFERENCA, "!=", linha, TokenType.OPERADOR));                // Operador !=
                            ponteiro++;                                             // Ignora a proxima posicao do vetor 'fonte', pois o operador eh composto por 2 caracteres
                        } else // Caso contrário, é um lexema inválido
                        {
                            caracterInvalido();
                            STATE = 0;                                              // Se o caracter seguinte a '!' nao for um '=', um erro foi encontrado...
                        }
                        /* Se '!' estiver no fim da linha, o codigo tentara acessar uma posicao inexistente do  vetor 'fonte'
                         * este comando ira gerar uma excecao que sera tratada inserindo-se o erro de caracter invalido na lista de erros;
                         */
                    } catch (ArrayIndexOutOfBoundsException e) {
                        listErro.add(new Erro("CARACTER INVALIDO", String.valueOf(fonte[ponteiro]), linha));
                        STATE = 0;
                    } finally {
                        break;
                    }
            case 38:
                    try {
                        if (fonte[ponteiro + 1] == 38) {
                            listagem.add(new Token(TokenAll.E, "E", linha, TokenType.OPERADOR));                    // Operador &&
                            ponteiro++;
                        } else //Caso contrário, é um lexema inválido
                        {
                            caracterInvalido();
                            //listErro.add(new Erro("CARACTER INVALIDO", this.lexemaErrado(), linha));
                            STATE = 0;
                        }
                    } catch (ArrayIndexOutOfBoundsException e) {
                        listErro.add(new Erro("CARACTER INVALIDO", String.valueOf(fonte[ponteiro]), linha));
                        STATE = 0;
                    } finally {
                        break;
                    }
            case 42:
                    listagem.add(new Token(TokenAll.MULTIPLICACAO, "*", linha, TokenType.OPERADOR));                       // Operador *
                    STATE = 0;
                    break;
            case 43:
                    if (!this.isFimPonteiro() && fonte[ponteiro + 1] == 43) {
                        listagem.add(new Token(TokenAll.INCREMENTO, "++", linha, TokenType.OPERADOR));          // Operador ++
                        ponteiro++;
                    } else {
                        listagem.add(new Token(TokenAll.SOMA, "+", linha, TokenType.OPERADOR));                   // Operador +
                    }
                    break;
            case 45:
                    if (!this.isFimPonteiro() && fonte[ponteiro + 1] == 45) {
                        listagem.add(new Token(TokenAll.DECREMENTO, "--", linha, TokenType.OPERADOR));          // Operador --
                        ponteiro++;
                    } else {
                        listagem.add(new Token(TokenAll.SUBTRACAO, "-", linha, TokenType.OPERADOR));                  // Operador -
                    }
                    break;
            case 47:
                    listagem.add(new Token(TokenAll.DIVISAO, "/", linha, TokenType.OPERADOR));                   // Operador /
                    break;
            case 60:
                    if (!this.isFimPonteiro() && fonte[ponteiro + 1] == 61) {
                        listagem.add(new Token(TokenAll.MENOR_IGUAL, "<=", linha, TokenType.OPERADOR));        // Operador <=
                        ponteiro++;
                    } else {
                        listagem.add(new Token(TokenAll.MENOR, "<", linha, TokenType.OPERADOR));               // Operador <
                    }
                    break;
            case 61:
                    if (!this.isFimPonteiro() && fonte[ponteiro + 1] == 61) {
                        listagem.add(new Token(TokenAll.IGUALDADE, "==", linha, TokenType.OPERADOR));                 // Operador ==
                        ponteiro++;
                    } else {
                        listagem.add(new Token(TokenAll.ATRIBUICAO, "=", linha, TokenType.OPERADOR));             // Operador =
                    }
                    break;
            case 62:
                    if (!this.isFimPonteiro() && fonte[ponteiro + 1] == 61) {
                        listagem.add(new Token(TokenAll.MAIOR_IGUAL, ">=", linha, TokenType.OPERADOR));         // Operador >=
                        ponteiro++;
                    } else {
                        listagem.add(new Token(TokenAll.MAIOR, ">", linha, TokenType.OPERADOR));               // Operador >
                    }
                    break;
            case 124:
                    try {
                        if (fonte[ponteiro + 1] == 124) {
                            listagem.add(new Token(TokenAll.OU, "OU", linha, TokenType.OPERADOR));                // Operador ||
                            ponteiro++;
                        } else //Caso contrário, é um lexema inválido
                        {
                            caracterInvalido();
                            //listErro.add(new Erro("CARACTER INVALIDO", this.lexemaErrado(), linha));
                            STATE = 0;
                        }
                    } catch (ArrayIndexOutOfBoundsException e) {
                        listErro.add(new Erro("CARACTER INVALIDO", String.valueOf(fonte[ponteiro]), linha));
                        STATE = 0;
                    }
                    break;
            case 46:
                    listagem.add(new Token(TokenAll.PONTO, ".", linha, TokenType.OPERADOR));                // Operador .
                    STATE = 0;
                    break;
        }
        STATE = 0;
    }

    public boolean ehOperador() {

        if (fonte[ponteiro] == 33 || fonte[ponteiro] == 38
                || fonte[ponteiro] == 42 || fonte[ponteiro] == 43
                || fonte[ponteiro] == 45 || fonte[ponteiro] == 60
                || fonte[ponteiro] == 61 || fonte[ponteiro] == 62
                || fonte[ponteiro] == 124 || fonte[ponteiro] == 46)
            return true;
    return false;
    }
/*
 *  By Ciro Marx
 */
    public boolean ehOperador(char c) {

        if (c == 33 || c == 38
                || c == 42 || c == 43
                || c == 45 || c == 60
                || c == 61 || c == 62
                || c == 124 || c == 46)
            return true;
    return false;
    }


    public void comentario()
    {
        int flag = 0;
        if(coment == 1)
            ponteiro--;

        while(fonte[ponteiro] != 42 || fonte[ponteiro+1] != 47)  // Se os dois caracteres não forem */
        {
            incrPonteiro();
            if(ponteiro+1 == fonte.length)   // Verifica se chegou ao termino da linha sem encontrar o */
            {
                flag = 1; // O coment sinaliza que a próxima linha começa como comentário
                break;
            }
            coment = 0;
        }
        if(flag == 1)
            coment = 1;
        else
            coment = 0;

        incrPonteiro();
        STATE = 0;
    }

    /*
     *
     */
    public boolean isDelimitador() {
        if (fonte[ponteiro] == 59 || fonte[ponteiro] == 40
                || fonte[ponteiro] == 41 || fonte[ponteiro] == 44 || fonte[ponteiro] == 91
                || fonte[ponteiro] == 93 || fonte[ponteiro] == 123 || fonte[ponteiro] == 125) {
            return true;
        } else {
            return false;
        }
    }
    /*
     *  By Ciro Marx
     */
    public boolean isDelimitador(char c) {
        if (c == 59 || c == 40
                || c == 41 || c == 91
                || c == 93 || c == 123 || c == 125) {
            return true;
        } else {
            return false;
        }
    }

    /*
     *
     */
    public void delimitador() {
        switch (fonte[ponteiro]) {
            case 59:
                listagem.add(new Token(TokenAll.PONTOEVIRGULA, ";", linha, TokenType.DELIMITADOR));              // Delimitador ;
                break;
            case 40:
                listagem.add(new Token(TokenAll.ABREPARENTESES, "(", linha, TokenType.DELIMITADOR));             // Delimitador (
                break;
            case 41:
                listagem.add(new Token(TokenAll.FECHAPARENTESES, ")", linha, TokenType.DELIMITADOR));             // Delimitador )
                break;
            case 44:
                listagem.add(new Token(TokenAll.VIRGULA, ",", linha, TokenType.DELIMITADOR));             // Delimitador )
                break;
            case 91:
                listagem.add(new Token(TokenAll.ABRECHOCHETES, "[", linha, TokenType.DELIMITADOR));             // Delimitador [
                break;
            case 93:
                listagem.add(new Token(TokenAll.FECHACOCHETES, "]", linha, TokenType.DELIMITADOR));             // Delimitador ]
                break;
            case 123:
                listagem.add(new Token(TokenAll.ABRECHAVES, "{", linha, TokenType.DELIMITADOR));             // Delimitador {
                break;
            case 125:
                listagem.add(new Token(TokenAll.FECHACHAVES, "}", linha, TokenType.DELIMITADOR));             // Delimitador }
                break;
        }
        this.STATE = 0;
    }

    public void setFonte(String fonte) {
        this.fonte = fonte.toCharArray();
    }

    /*
     *
     */
    public String lexemaErrado() {
        String lexema = String.valueOf(fonte[ponteiro]);
        while (!this.isFimPonteiro() && fonte[ponteiro + 1] != 32) //Enquanto o próximo caractere não for " ", forma-se o lexema invalido
        {
            incrPonteiro();
            if(ehOperador() || isDelimitador())
            {
                ponteiro--;
                break;
            }
            lexema = lexema + String.valueOf(fonte[ponteiro]);
        }
        ponteiro--;
        return lexema;
    }

    /**
     * Identica o caractere invalido e redireciona para para o autômato certo
     * @param c
     * @return
     */
    public void caracterInvalido()
    {
        if(!this.isValidChar(fonte[ponteiro])) //Verifica se de fato o caractere é inválido
        {
            System.out.println("Entrou aqui! -->" + fonte[ponteiro]);
            try
            {
                if(this.fonte[ponteiro+1] == ' ' || this.ehOperador(fonte[ponteiro+1]) || this.isDelimitador(fonte[ponteiro+1]) || this.isQuebra(fonte[ponteiro+1]))
                    listErro.add(new Erro("CARACTER INVALIDO", String.valueOf(fonte[ponteiro]), linha));
                else if(Character.isLetter(this.fonte[ponteiro+1]) || this.fonte[ponteiro+1] == '_')
                    this.identificador();
                else if(Character.isDigit(fonte[ponteiro+1]))
                    this.numero();
            }
            catch(ArrayIndexOutOfBoundsException e)     //Garante o tratamento da exceção em caso de estouro de vetor
            {
                listErro.add(new Erro("CARACTER INVALIDO", String.valueOf(fonte[ponteiro]), linha));
            }

        }
        STATE = 0;
    }
    /*public void caracterInvalido()
    {
        Token temp = null;
        String lexema = "";
        int antes = ponteiro;
        antes--;

        System.out.println(":: " + fonte[ponteiro]);
        System.out.println("Valor de antes: "+ antes);
        
        if(antes < 0 && listagem.isEmpty())
        {
            listErro.add(new Erro("CARACTER INVALIDO", this.lexemaErrado(), linha));
            //throw new ErroLexicoException( this.lexemaErrado(), "Caractere Invalido", 112345);
        } else if(fonte[antes] == 32)
        {
            listErro.add(new Erro("CARACTER INVALIDO", this.lexemaErrado(), linha));
            //throw new ErroLexicoException( this.lexemaErrado(), "Caractere Invalido", 122345);
        } else if(listagem.get(listagem.size()-1).geteToke() == TokenType.IDENTIFICADOR || listagem.get(listagem.size()-1).geteToke() == TokenType.NUMERO)
        {
            temp = listagem.get(listagem.size()-1);
            if (temp.getTipo() == TokenAll.IDENTIFICADOR) {
                lexema = temp.getValor();
                listagem.remove(temp);
            }else if (temp.getTipo() == TokenAll.NUMERO) {
                lexema = String.valueOf((int)temp.getValorNum());
                listagem.remove(temp);
            }
            //throw new ErroLexicoException(lexema.concat(this.lexemaErrado()), "Caractere Invalido", 123345);
            listErro.add(new Erro("CARACTER INVALIDO", lexema.concat(this.lexemaErrado()), linha));
        }else
            listErro.add(new Erro("CARACTER INVALIDO", this.lexemaErrado(), linha));

        incrPonteiro();
        STATE = 0;
    }*/

    /*
     *
     */
    public void caractere() {
        int temp = 0;

        incrPonteiro();
        String aux = "\'" + fonte[ponteiro];
        incrPonteiro();
        if (fonte[ponteiro] != 39) {
            while (fonte[ponteiro] != 39) {
                aux += fonte[ponteiro];
                incrPonteiro();
                if(ponteiro == fonte.length-1)
                {
                    temp = 1;
                    break;
                }
            }
            aux += "\'";
            if(temp == 0)
            listErro.add(new Erro("FORMATO INVALIDO", aux, linha));
            else
                listErro.add(new Erro("FINAL DE CARACTERE NÃO ENCONTRADO", aux, linha));
        } else {
            aux += "\'";
            listagem.add(new Token(TokenAll.CHAR, aux, linha, TokenType.CHAR));
        }
        STATE = 0;
    }

    public void string() {

        int inicio = ponteiro;  // Guarda a posicao da primeira ocorrencia das aspas (");

        try {
            do {                    // Incrementa o ponteiro, ate encontrar as segundas aspas (");
                ponteiro++;
            } while (fonte[ponteiro] != 34);

            String str = new String(fonte).substring(inicio, ponteiro + 1);     // Pega a sequencia de caracteres entre as aspas...

            // Armazena na lista de Tokens...
            listagem.add(new Token(TokenAll.STRING, str, linha, TokenType.STRING));
        } catch (ArrayIndexOutOfBoundsException e) {                      // Se as segundas aspas nao foram encontradas...
            listErro.add(new Erro("FINAL DE STRING NÃO ENCONTRADO", "\"", linha));
        }
        STATE = 0;
    }
/*
 *  By Ciro Marx
 */
    public boolean isValidChar(char c)
    {
        if(Character.isDigit(c) || Character.isLetter(c) || Character.isSpaceChar(c) || this.isQuebra(c))
        {    if((c=='&' && fonte[ponteiro+1]!='&') || (c=='!' && fonte[ponteiro+1]!='='))
                return false;
            else
                return true;
        }
        else
            return false;
    }

    public List<Token> getListagem() {
        return listagem;
    }

    public void setListagem(List<Token> listagem) {
        this.listagem = listagem;
    }

    public int getLinha() {
        return linha;
    }

    public void setLinha(int linha) {
        this.linha = linha;
    }

    public void pularLinha()
    {
        while(fonte[ponteiro] != 3)
        {
            ponteiro++;
        }
    }

    public List<Erro> getListErro() {
        return listErro;
    }

    public void setListErro(List<Erro> listErro) {
        this.listErro = listErro;
    }

    public int getComent() {
        return coment;
    }

    public void setComent(int coment) {
        this.coment = coment;
    }
}